﻿using Tszy.Unlimited.Base.Collections;

namespace Tszy.Unlimited.Base.Objects.Methods
{
    /// <summary>
    ///
    /// </summary>
    public class MethodManager
    {
        private readonly MonoConcurrentDictionary<string, IExecuteMethod0> _methods0 = new MonoConcurrentDictionary<string, IExecuteMethod0>();
        private readonly MonoConcurrentDictionary<string, IExecuteMethod1> _methods1 = new MonoConcurrentDictionary<string, IExecuteMethod1>();
        private readonly MonoConcurrentDictionary<string, IExecuteMethod2> _methods2 = new MonoConcurrentDictionary<string, IExecuteMethod2>();

        /// <summary>
        /// 当前实体管理器。
        /// </summary>
        public static MethodManager Instance = new MethodManager();

        /// <summary>
        /// 动态调用目标对象的指定方法（0个参数）。
        /// </summary>
        /// <param name="target">目标对象。</param>
        /// <param name="methodName">方法名。</param>
        /// <returns></returns>
        public bool Invoke(object target, string methodName)
        {
            var targetType = target.GetType();

            var key = $"method_name_{methodName}_{targetType.FullName}_0";

            IExecuteMethod0 methodWrapper;

            if (_methods1.ContainsKey(key))
            {
                methodWrapper = _methods0[key];
            }
            else
            {
                methodWrapper = MethodWarpper.GetMethodWrapper(methodName, targetType);

                if (methodWrapper != null)
                {
                    _methods0.Add(key, methodWrapper);
                }
            }

            if (methodWrapper != null)
            {
                //执行性能与直接调用差不多。
                methodWrapper.Execute(target);

                return true;
            }

            return false;
        }

        /// <summary>
        /// 动态调用目标对象的指定方法（1个参数）。
        /// </summary>
        /// <param name="target">目标对象。</param>
        /// <param name="methodName">方法名。</param>
        /// <param name="parameter">参数。</param>
        /// <returns></returns>
        public bool Invoke(object target, string methodName, object parameter)
        {
            var targetType = target.GetType();
            var parameterType = parameter.GetType();

            var key = $"method_name_{methodName}_{targetType.FullName}_{parameterType.FullName}";

            IExecuteMethod1 methodWrapper;

            if (_methods1.ContainsKey(key))
            {
                methodWrapper = _methods1[key];
            }
            else
            {
                methodWrapper = MethodWarpper.GetMethodWrapper(methodName, targetType, parameterType);

                if (methodWrapper != null)
                {
                    _methods1.Add(key, methodWrapper);
                }
            }

            if (methodWrapper != null)
            {
                //执行性能与直接调用差不多。
                methodWrapper.Execute(target, parameter);

                return true;
            }

            return false;
        }

        /// <summary>
        /// 动态调用目标对象的指定方法（2个参数）。
        /// </summary>
        /// <param name="target">目标对象。</param>
        /// <param name="methodName">方法名。</param>
        /// <param name="parameter1">参数1。</param>
        /// <param name="parameter2">参数2。</param>
        /// <returns></returns>
        public bool Invoke(object target, string methodName, object parameter1, object parameter2)
        {
            var targetType = target.GetType();
            var parameterType1 = parameter1.GetType();
            var parameterType2 = parameter2.GetType();

            var key = $"method_name_{methodName}_{targetType.FullName}_{parameterType1.FullName}_{parameterType2.FullName}";

            IExecuteMethod2 methodWrapper = null;

            if (_methods1.ContainsKey(key))
            {
                methodWrapper = _methods2[key];
            }

            if (methodWrapper == null)
            {
                if (_methods2.ContainsKey(key))
                {
                    methodWrapper = _methods2[key];
                }

                if (methodWrapper == null)
                {
                    methodWrapper = MethodWarpper.GetMethodWrapper(methodName, targetType, parameterType1, parameterType2);

                    if (methodWrapper != null)
                    {
                        _methods2.Add(key, methodWrapper);
                    }
                }
            }

            if (methodWrapper != null)
            {
                //执行性能与直接调用差不多。
                methodWrapper.Execute(target, parameter1, parameter2);

                return true;
            }

            return false;
        }
    }
}